package cn.com.eth.yx.ethpro.service.impl;//package cn.com.jdyun.service.impl;

import cn.com.eth.yx.ethpro.service.EthService;
import cn.com.eth.yx.ethpro.util.EthUtil;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.web3j.abi.FunctionEncoder;
import org.web3j.abi.TypeReference;
import org.web3j.abi.datatypes.Address;
import org.web3j.abi.datatypes.Function;
import org.web3j.abi.datatypes.generated.Uint256;
import org.web3j.crypto.Credentials;
import org.web3j.crypto.RawTransaction;
import org.web3j.crypto.TransactionEncoder;
import org.web3j.crypto.WalletUtils;
import org.web3j.protocol.Web3j;
import org.web3j.protocol.core.DefaultBlockParameterName;
import org.web3j.protocol.core.methods.response.EthGetTransactionCount;
import org.web3j.protocol.core.methods.response.EthSendTransaction;
import org.web3j.utils.Numeric;

import java.math.BigInteger;
import java.util.Arrays;

/**
 * @author admin
 */
@Service
public class EthServiceImpl implements EthService {

    @Transactional(rollbackFor = Exception.class)
    @Override
    public String tranferToContractAddr(Web3j web3j, String from, String to, String value, String gasPrice, String gasLimit, String walletPwd) throws Exception {

        BigInteger balance = web3j.ethGetBalance(from, DefaultBlockParameterName.LATEST).send().getBalance();

        BigInteger gasPrice1 = new BigInteger(gasPrice);
        BigInteger gasLimit1 = new BigInteger(gasLimit);
        BigInteger gas = gasPrice1.multiply(gasLimit1);
//        double temp = Math.pow(10, TokenOperate.DECIMAL);
        BigInteger amount = new BigInteger(value);
        BigInteger allFee = amount.add(gas);
        //获取账户余额
//        System.out.println(from + " balance :" + balance);
        if (balance.compareTo(allFee) < 0) {
            throw new Exception("账户余额不足");
        }
        //交易凭证
        Credentials credentials = WalletUtils.loadCredentials(walletPwd, EthUtil.getFileFromAddress(from));

        EthGetTransactionCount ethGetTransactionCount = web3j.ethGetTransactionCount(
                from, DefaultBlockParameterName.LATEST).sendAsync().get();
        BigInteger nonce = ethGetTransactionCount.getTransactionCount();

//创建交易  注意金额 保留小数点后8位 要转化为整数 比如0.00000001 转化为1
        Function function = new Function(
                "_transfer",//交易的方法名称
                Arrays.asList(new Address(from), new Uint256(amount)),
                Arrays.asList(new TypeReference<Address>() {
                }, new TypeReference<Uint256>() {
                })
        );
        String encodedFunction = FunctionEncoder.encode(function);

        //智能合约交易
        RawTransaction rawTransaction = RawTransaction.createTransaction(nonce, gasPrice1, gasLimit1, to, encodedFunction);

        byte[] signedMessage = TransactionEncoder.signMessage(rawTransaction, credentials);
        String hexValue = Numeric.toHexString(signedMessage);
        //发送交易
        EthSendTransaction ethSendTransaction = web3j.ethSendRawTransaction(hexValue).sendAsync().get();
        //交易的HASH
        String transactionHash = ethSendTransaction.getTransactionHash();
        return transactionHash;

    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public String tranferEth(Web3j web3j, String from, String to, String amount, String gasPrice1, String gasLimit1, String walletPwd) throws Exception {
        //查询交易费
        BigInteger gasPrice = new BigInteger(gasPrice1);
        BigInteger gasLimit = new BigInteger(gasLimit1);
        BigInteger gas = gasPrice.multiply(gasLimit);
        BigInteger value = new BigInteger(amount);
        BigInteger allFee = value.add(gas);
        String transactionHash;
        //获取指定钱包的以太币余额
        try {
            BigInteger balance = web3j.ethGetBalance(from, DefaultBlockParameterName.LATEST).send().getBalance();
            if (balance.compareTo(allFee) < 0) {
                throw new Exception("账户余额不足");
            }
            //交易凭证
            Credentials credentials = WalletUtils.loadCredentials(walletPwd, EthUtil.getFileFromAddress(from));
            EthGetTransactionCount ethGetTransactionCount = web3j.ethGetTransactionCount(
                    from, DefaultBlockParameterName.LATEST).sendAsync().get();
            BigInteger nonce = ethGetTransactionCount.getTransactionCount();
            //普通交易
            RawTransaction rawTransaction = RawTransaction.createEtherTransaction(
                    nonce, gasPrice, gasLimit, to, value);

            byte[] signedMessage = TransactionEncoder.signMessage(rawTransaction, credentials);
            String hexValue = Numeric.toHexString(signedMessage);
            //发送交易
            EthSendTransaction ethSendTransaction = web3j.ethSendRawTransaction(hexValue).sendAsync().get();
            //交易的HASH
            transactionHash = ethSendTransaction.getTransactionHash();
        } catch (Exception e) {
            throw new Exception("转账失败!");
        }
        return transactionHash;
    }

}
